﻿using SharpErp.Data.Common.Entity;
using SharpErp.Data.Common.Entity.Department;
using SharpErp.Data.Common.View;
using System;
using System.Collections.Generic;
using System.Linq;

namespace SharpErp.Data.Service
{
    public partial class SharpErpServiceImpl : ISharpErpService
    {
        public List<CompanyStaff> GetSysCompanyStaffsByParentId(int parentId)
        {
            using (var context = new Common.Context.SharpErpDbContext())
            {
                return new List<CompanyStaff>(context.SelectAll(context.CompanyStaffs,
                    p => p.ParentId == parentId && (p.SystemFlag & BaseEntity.SYS_FLAG_DELETE) == 0));
            }
        }
        public List<Common.Entity.Department.CompanyStaff> GetAllSysCompanyStaffs()
        {
            using (var context = new Common.Context.SharpErpDbContext())
            {
                return new List<CompanyStaff>(context.SelectAll(context.CompanyStaffs, p=>(p.SystemFlag & BaseEntity.SYS_FLAG_DELETE) == 0));
            }
        }

        public List<Common.Entity.Department.CompanyStaff> GetAllSetShareCompanyStaffs()
        {
            using (var context = new Common.Context.SharpErpDbContext())
            {
                return context.CompanyStaffs.Where(p=>(p.SystemFlag & BaseEntity.SYS_FLAG_DELETE) == 0 && p.SetShare == 0).ToList();
            }
        }
        public List<Common.Entity.Department.CompanyStaff> GetAllSysCompanyStaffBySetAccountName(string setAccountName)
        {
            if (string.IsNullOrEmpty(setAccountName) || setAccountName.Equals("默认账套") || setAccountName.Equals("公用账套")) return GetAllSetShareCompanyStaffs();
            var setAccount = GetSetAccountInfoByName(setAccountName);
            if(setAccount == null) return GetAllSysCompanyStaffs();
            using (var context = new Common.Context.SharpErpDbContext())
            {
                var query = context.CompanyStaffs.Where(p=>(p.SystemFlag & BaseEntity.SYS_FLAG_DELETE) == 0);
                if (setAccount.SetShare > 0)
                {
                    query = query.Where(p => p.SetShare == setAccount.SetShare && p.SetId == setAccount.Id);
                }
                else
                {
                    query = query.Where(p => p.SetShare == 0);
                }
                return query.ToList();
            }
        }

        public int AddCompanyStaff(CompanyStaff item)
        {
            using (var context = new Common.Context.SharpErpDbContext())
            {
                int id = context.Add(context.CompanyStaffs, item).Id;
                this.updateCashBank();
                return id;
            }
        }

        public void UpdateCompanyStaff(CompanyStaff item)
        {
            using (var context = new Common.Context.SharpErpDbContext())
            {
                context.Update(context.CompanyStaffs, item);
                this.updateCashBank();
            }
        }

        public void DeleteCompanyStaff(int id)
        {
            using (var context = new Common.Context.SharpErpDbContext())
            {
                context.Delete(context.CompanyStaffs, p => p.Id == id);
                this.updateCashBank();
            }
        }

        private void updateCashBank()
        {

            using (var context = new Common.Context.SharpErpDbContext())
            {
                var staffs = new List<CompanyStaff>(context.SelectAll(context.CompanyStaffs, p=>(p.SystemFlag & BaseEntity.SYS_FLAG_DELETE) == 0));
                var cashBanks = GetAllSysCashBankSecondClass();
                foreach (var item in cashBanks) item.Staff = "";
                foreach(var staff in staffs)
                {
                    if (string.IsNullOrEmpty(staff.Account)) continue;
                    string[] accounts = staff.Account.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                    foreach(var account in accounts)
                    {
                        foreach(var cashBank in cashBanks)
                        {
                            if (cashBank.Name.Equals(account))
                            {
                                if (string.IsNullOrEmpty(cashBank.Staff)) cashBank.Staff = staff.Name;
                                else cashBank.Staff = cashBank.Staff + ", " + staff.Name;
                            }
                        }
                    }
                }
                if(cashBanks != null && cashBanks.Count > 0)
                {
                    SetAllKvItemClass<CashBankSecondClass>(cashBanks, KVEntity.KEY_CASHBANK_SECOND_CLASS);
                }
            }
        }

        public List<CompanyAsset> GetSysCompanyAssetsByParentId(int parentId)
        {
            using (var context = new Common.Context.SharpErpDbContext())
            {
                return new List<CompanyAsset>(context.SelectAll(context.CompanyAssets,
                    p => p.ParentId == parentId && (p.SystemFlag & BaseEntity.SYS_FLAG_DELETE) == 0));
            }
        }

        public List<CompanyAsset> GetSysCompanyAssetsByParentIds(HashSet<int> ids)
        {
            using (var context = new Common.Context.SharpErpDbContext())
            {
                return new List<CompanyAsset>(context.SelectAll(context.CompanyAssets,
                    p => ids.Contains(p.ParentId) && (p.SystemFlag & BaseEntity.SYS_FLAG_DELETE) == 0));
            }
        }

        public void AddCompanyAsset(CompanyAsset item)
        {
            using (var context = new Common.Context.SharpErpDbContext())
            {
                context.Add(context.CompanyAssets, item);
            }
        }

        public void UpdateCompanyAsset(CompanyAsset item)
        {
            using (var context = new Common.Context.SharpErpDbContext())
            {
                context.Update(context.CompanyAssets, item);
            }
        }

        public void BatchUpdateCompanyAsset(List<Common.Entity.Department.CompanyAsset> items)
        {
            using (var context = new Common.Context.SharpErpDbContext())
            {
                foreach(var item in items)
                {
                    if (item.Id > 0) context.Update(context.CompanyAssets, item);
                    else context.Add(context.CompanyAssets, item);
                }
            }
        }

        public void DeleteCompanyAsset(int id)
        {
            using (var context = new Common.Context.SharpErpDbContext())
            {
                context.Delete(context.CompanyAssets, p=>p.Id == id);
            }
        }

        public List<CompanyDepartment> GetSysCompanyDepartments()
        {
            var list = GetAllKvItemClass<CompanyDepartment>(KVEntity.KEY_COMPANY_DEPARTMENT);
            if (list == null || !list.Any())
            {
                return list;
            }
            return list.Where(p => (p.SystemFlag & BaseEntity.SYS_FLAG_DELETE) == 0).ToList();
        }

        public int AddCompanyDepartment(CompanyDepartment item)
        {
            var items = GetAllKvItemClass<CompanyDepartment>(KVEntity.KEY_COMPANY_DEPARTMENT);
            var maxId = 1;
            if (items != null && items.Any()) maxId = (from p in items select p.Id).Max() + 1;
            item.Id = maxId;
            item.CreateTime = item.LastModifyTime = new DateTime();
            if (items == null) return -1;
            items.Add(item);
            SetAllKvItemClass(items, KVEntity.KEY_COMPANY_DEPARTMENT);
            return maxId;
        }



        public void UpdateCompanyDepartment(CompanyDepartment item)
        {
            using (var context = new Common.Context.SharpErpDbContext())
            {
                var items = GetAllKvItemClass<CompanyDepartment>(KVEntity.KEY_COMPANY_DEPARTMENT);
                for (var i = 0; i < items.Count(); ++i)
                {
                    if (items[i].Id != item.Id) continue;
                    items[i].LastModifyTime = new DateTime();
                    items[i].Name = item.Name;
                    break;
                }
                SetAllKvItemClass(items, KVEntity.KEY_COMPANY_DEPARTMENT);
            }
        }

        public void DeleteCompanyDepartment(int id)
        {
            using (var context = new Common.Context.SharpErpDbContext())
            {
                var items = GetAllKvItemClass<CompanyDepartment>(KVEntity.KEY_COMPANY_DEPARTMENT);
                for (int i = 0; i < items.Count(); ++i)
                {
                    if (items[i].Id == id)
                    {
                        items[i].LastModifyTime = new DateTime();
                        items[i].SystemFlag |= BaseEntity.SYS_FLAG_DELETE;
                        break;
                    }
                }
                SetAllKvItemClass(items, KVEntity.KEY_COMPANY_DEPARTMENT);
            }
        }

        public CompanyStaffView doLogin(string name, string password, string setAccount, DateTime time)
        {

            using (var context = new Common.Context.SharpErpDbContext())
            {
                CompanyStaff staff = null;
                if(string.Equals("admin", name) && string.Equals("admin", password))
                {
                    staff = new CompanyStaff
                    {
                        Name = "admin",
                        PasswordMd5 = "",
                        Id = 100000000,
                    };
                }
                else
                {
                    var list = context.CompanyStaffs.Where(p => string.Equals(p.Name, name)).ToList();
                    if (list != null && list.Count > 0) staff = list[0];
                }
                if (staff == null || (staff.SystemFlag & BaseEntity.SYS_FLAG_DELETE) > 0 || 
                    (!string.IsNullOrEmpty(staff.PasswordMd5) && !string.Equals(staff.PasswordMd5, SharpErp.Common.Util.Md5Util.MD5Encrypt(password)))) return null;
                var setAccounts = GetSysSetAccount();
                int setId = 0, setShare = 0;
                if(string.IsNullOrEmpty(setAccount) || setAccount.Equals("默认账套") || setAccounts == null || setAccounts.Count <= 0)
                {
                    SharpErp.Common.Util.Logger.GetLog().Warn("use default set account:" + name + ", " + password + ", " + setAccount);
                    staff.SetId = setId;
                    staff.SetShare = setShare;
                }
                else
                {
                    var account = setAccounts.Find(p=>string.Equals(p.Name, setAccount) && (p.SystemFlag & BaseEntity.SYS_FLAG_DELETE) == 0 );
                    if (account == null) return null;
                    staff.SetId = account.Id;
                    staff.SetShare = account.SetShare;
                }
                var result = new CompanyStaffView();
                SharpErp.Common.Util.BeanUtils.CopyTo(staff, result);
                result.Department = setAccount;
                if(GetCurrentSession != null)
                {
                    GetCurrentSession.Invoke().SessionData = result;
                    SharpErp.Common.Util.Logger.GetLog().Warn("user login success:" + result);

                }
                return result;

            }
        }
        public bool modifyPassword(string name, string oldPassword, string newPassword)
        {
            using (var context = new Common.Context.SharpErpDbContext())
            {
                var staff = context.SelectOne(context.CompanyStaffs, p => string.Equals(p.Name, name));
                if (staff == null || (staff.SystemFlag & BaseEntity.SYS_FLAG_DELETE) > 0 ||
                    (!string.IsNullOrEmpty(staff.PasswordMd5) && !string.Equals(staff.PasswordMd5, SharpErp.Common.Util.Md5Util.MD5Encrypt(oldPassword)))) return false;
                var setAccounts = GetSysSetAccount();
                staff.PasswordMd5 = SharpErp.Common.Util.Md5Util.MD5Encrypt(newPassword);
                context.Update(context.CompanyStaffs, staff);
                return true;
            }
        }

    }
}
